"""
请求库的轻量级包装器，支持异步。

@Date    : 2023/12/19 9:14
@Author  : sam sho
"""
from contextlib import asynccontextmanager
from typing import Any, Dict, Optional, AsyncGenerator

import aiohttp
import requests


class RestTemplate:
    """
    封装请求来处理安全验证和异步。
    这个包装器的主要目的是处理身份验证(通过存储请求头验证信息)
    并在同一个基对象上启用简单的异步方法。
    """

    headers: Optional[Dict[str, str]] = None
    aiosession: Optional[aiohttp.ClientSession] = None
    auth: Optional[Any] = None

    """Get请求URL地址并返回 Response 对象数据。"""

    def get(self, url: str, **kwargs: Any) -> requests.Response:
        return requests.get(url, headers=self.headers, auth=self.auth, **kwargs)

    """Get请求URL地址并返回 Response 对象数据。"""

    def get(self, url: str, params=None, **kwargs: Any) -> requests.Response:
        return requests.get(url, params=params, headers=self.headers, auth=self.auth, **kwargs)

    """
    POST请求URL地址并返回数据。    
    @data : Dict 类型数据
    """

    def post(self, url: str, data: Dict[str, Any], **kwargs: Any) -> requests.Response:
        return requests.post(
            url, json=data, headers=self.headers, auth=self.auth, **kwargs
        )

    """
    DELETE请求URL地址并返回数据。    
    """

    def delete(self, url: str, **kwargs: Any) -> requests.Response:
        return requests.delete(url, headers=self.headers, auth=self.auth, **kwargs)

    """
    异步请求实现    
    """

    @asynccontextmanager
    async def asyn_request(
            self, method: str, url: str, **kwargs: Any
    ) -> AsyncGenerator[aiohttp.ClientResponse, None]:
        """创建异步请求对象"""
        if not self.aiosession:
            async with aiohttp.ClientSession() as session:
                async with session.request(
                        method, url, headers=self.headers, auth=self.auth, **kwargs
                ) as response:
                    yield response
        else:
            async with self.aiosession.request(
                    method, url, headers=self.headers, auth=self.auth, **kwargs
            ) as response:
                yield response

    """
    异步Get请求URL地址并返回 ClientResponse 对象数据。
    @data : Dict 类型数据
    """

    @asynccontextmanager
    async def asyn_get(
            self, url: str, **kwargs: Any
    ) -> AsyncGenerator[aiohttp.ClientResponse, None]:
        async with self.asyn_request("GET", url, **kwargs) as response:
            yield response

    """
    异步POST请求URL地址并返回 ClientResponse 对象数据。
    @data : Dict 类型数据
    """

    @asynccontextmanager
    async def asyn_post(
            self, url: str, data: Dict[str, Any], **kwargs: Any
    ) -> AsyncGenerator[aiohttp.ClientResponse, None]:
        async with self.asyn_request("POST", url, json=data, **kwargs) as response:
            yield response

    """
    异步DELETE请求URL地址并返回 ClientResponse 对象数据。
    """

    @asynccontextmanager
    async def asyn_delete(
            self, url: str, **kwargs: Any
    ) -> AsyncGenerator[aiohttp.ClientResponse, None]:
        """DELETE the URL and return the text asynchronously."""
        async with self.asyn_request("DELETE", url, **kwargs) as response:
            yield response
